{
 "cells": [
  {
   "cell_type": "code",
   "id": "initial_id",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-05-22T03:53:05.058038Z",
     "start_time": "2025-05-22T03:53:00.069108Z"
    }
   },
   "source": [
    "import torch\n",
    "\n",
    "# 检查 CUDA 是否可用\n",
    "print(torch.cuda.is_available())\n",
    "\n",
    "if torch.cuda.is_available():\n",
    "    # 获取可用的 CUDA 设备数量\n",
    "    print(\"可用的 CUDA 设备数量:\", torch.cuda.device_count())\n",
    "    # 获取当前使用的 CUDA 设备索引\n",
    "    print(\"当前 CUDA 设备索引:\", torch.cuda.current_device())\n",
    "    # 获取指定索引 CUDA 设备的名称\n",
    "    print(\"当前 CUDA 设备名称:\", torch.cuda.get_device_name(0))\n",
    "\n",
    "    # 创建一个张量并将其移动到 CUDA 设备上\n",
    "    x = torch.tensor([1.0, 2.0]).cuda()\n",
    "    y = torch.tensor([3.0, 4.0]).cuda()\n",
    "    z = x + y\n",
    "    print(\"在 CUDA 上计算的结果:\", z)\n",
    "else:\n",
    "    print(\"CUDA 不可用\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "可用的 CUDA 设备数量: 1\n",
      "当前 CUDA 设备索引: 0\n",
      "当前 CUDA 设备名称: NVIDIA GeForce RTX 3060\n",
      "在 CUDA 上计算的结果: tensor([4., 6.], device='cuda:0')\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-22T04:04:32.511936Z",
     "start_time": "2025-05-22T04:04:30.835567Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import visdom\n",
    "import numpy as np\n",
    "\n",
    "# 创建 Visdom 连接\n",
    "viz = visdom.Visdom()\n",
    "\n",
    "# 生成一些数据点\n",
    "x = np.arange(1, 101)  # x轴从1到100\n",
    "y = x * 2 + np.random.randn(100) * 10  # y = 2x + 噪声\n",
    "\n",
    "# 绘制直线图\n",
    "viz.line(\n",
    "    Y=y,  # y轴数据\n",
    "    X=x,  # x轴数据\n",
    "    opts=dict(\n",
    "        title='简单直线图示例',\n",
    "        xlabel='X轴',\n",
    "        ylabel='Y轴',\n",
    "        showlegend=True\n",
    "    )\n",
    ")"
   ],
   "id": "f5f52cce7f337d0a",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Setting up a new session...\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'window_3e18efca1b72ee'"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 3
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-22T06:15:32.644510Z",
     "start_time": "2025-05-22T06:15:32.298845Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import visdom\n",
    "import numpy as np\n",
    "\n",
    "vis = visdom.Visdom()\n",
    "\n",
    "# 线图示例\n",
    "vis.line(\n",
    "    X=np.arange(10),\n",
    "    Y=np.random.rand(10),\n",
    "    opts=dict(title='Random Line', showlegend=True)\n",
    ")\n",
    "\n",
    "# 散点图示例\n",
    "vis.scatter(\n",
    "    X=np.random.rand(100, 2),\n",
    "    Y=(np.random.rand(100) > 0.5).astype(int)+1,\n",
    "    opts=dict(title='2D Scatter', markersize=10)\n",
    ")"
   ],
   "id": "d7e332a06ad69e08",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Setting up a new session...\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'window_3e19021739b10c'"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 10
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-22T06:18:27.719183Z",
     "start_time": "2025-05-22T06:18:27.445474Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import visdom\n",
    "import numpy as np\n",
    "\n",
    "vis = visdom.Visdom()\n",
    "\n",
    "# 初始化线图\n",
    "vis.line(\n",
    "    X=[0],\n",
    "    Y=[0.5],\n",
    "    win='loss',\n",
    "    opts=dict(title='Training Loss')\n",
    ")\n",
    "\n",
    "# 模拟训练过程\n",
    "for epoch in range(1, 10):\n",
    "    loss = np.random.rand() * 0.1 + 1.0/(epoch+1)\n",
    "    vis.line(\n",
    "        X=[epoch],\n",
    "        Y=[loss],\n",
    "        win='loss',\n",
    "        update='append'  # 关键参数，避免覆盖\n",
    "    )"
   ],
   "id": "71e0e7f1bed0a664",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Setting up a new session...\n"
     ]
    }
   ],
   "execution_count": 11
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-22T13:06:57.644930Z",
     "start_time": "2025-05-22T13:06:51.486704Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import visdom\n",
    "import numpy as np\n",
    "import time\n",
    "\n",
    "vis = visdom.Visdom(env='training_monitor')\n",
    "\n",
    "# 初始化所有窗口\n",
    "vis.line(X=[0], Y=[0], win='loss', opts=dict(title='Loss', legend=['Train', 'Val']))\n",
    "vis.line(X=[0], Y=[0], win='acc', opts=dict(title='Accuracy', legend=['Train', 'Val']))\n",
    "\n",
    "for epoch in range(1, 11):\n",
    "    # 模拟训练数据\n",
    "    train_loss = np.random.rand()*0.1 + 1.0/epoch\n",
    "    val_loss = np.random.rand()*0.1 + 1.2/epoch\n",
    "    train_acc = 1 - train_loss + np.random.rand()*0.1\n",
    "    val_acc = 1 - val_loss + np.random.rand()*0.1\n",
    "\n",
    "    # 更新损失曲线（两种方式等价）\n",
    "    vis.line(\n",
    "        X=[epoch], Y=[train_loss],\n",
    "        win='loss', name='Train',\n",
    "        update='append'\n",
    "    )\n",
    "    vis.line(\n",
    "        X=[epoch], Y=[val_loss],\n",
    "        win='loss', name='Val',\n",
    "        update='append'\n",
    "    )\n",
    "\n",
    "    # 更新准确率曲线\n",
    "    vis.line(\n",
    "        X=[epoch], Y=[train_acc],\n",
    "        win='acc', name='Train',\n",
    "        update='append'\n",
    "    )\n",
    "    vis.line(\n",
    "        X=[epoch], Y=[val_acc],\n",
    "        win='acc', name='Val',\n",
    "        update='append'\n",
    "    )\n",
    "\n",
    "    # 每5个epoch可视化一批样本\n",
    "    if epoch % 5 == 0:\n",
    "        samples = np.random.rand(16, 3, 64, 64)  # 模拟图像数据\n",
    "        vis.images(\n",
    "            samples,\n",
    "            win='samples',\n",
    "            opts=dict(title=f'Epoch {epoch} Samples')\n",
    "        )\n",
    "\n",
    "    time.sleep(0.5)  # 模拟训练时间"
   ],
   "id": "be24f90eab824f6d",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Setting up a new session...\n"
     ]
    }
   ],
   "execution_count": 3
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-22T13:20:05.553564Z",
     "start_time": "2025-05-22T13:20:05.309396Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import visdom\n",
    "import numpy as np\n",
    "\n",
    "vis=visdom.Visdom(env='training_monitor')\n",
    "\n",
    "Y=np.random.rand(100)\n",
    "\n",
    "old_scatter=vis.scatter(\n",
    "    X=np.random.rand(100,2),\n",
    "    Y=(Y[Y>0]+1.5).astype(int),\n",
    "    opts=dict(\n",
    "        legend=['Didnt', 'Update'], # 图例标签\n",
    "        xtickmin=-50, # x轴刻度最小值\n",
    "        xtickmax=50, # x轴刻度最大值\n",
    "        xtickstep=0.5, # x轴刻度间隔\n",
    "        ytickmin=-50, # y轴刻度最小值\n",
    "        ytickmax=50, # y轴刻度最大值\n",
    "        ytickstep=0.5, # y轴刻度间隔\n",
    "        markersymbol='cross-thin-open', # 标记符号\n",
    "    )\n",
    ")\n",
    "# 使用update_window_opts函数更新之前绘制的散点图的配置选项\n",
    "vis.update_window_opts(\n",
    "    win=old_scatter,\n",
    "    opts=dict(\n",
    "        legend=['2019年', '2020年'],\n",
    "        xtickmin=0,\n",
    "        xtickmax=1,\n",
    "        xtickstep=0.5,\n",
    "        ytickmin=0,\n",
    "        ytickmax=1,\n",
    "        ytickstep=0.5,\n",
    "        markersymbol='cross-thin-open',\n",
    "    ),\n",
    ")"
   ],
   "id": "8121cc8c272d4f6c",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Setting up a new session...\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'window_3e193d66425bc8'"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-22T13:23:32.440039Z",
     "start_time": "2025-05-22T13:23:32.316443Z"
    }
   },
   "cell_type": "code",
   "source": [
    "#带文本标签的散点图\n",
    "import visdom\n",
    "import numpy as np\n",
    "\n",
    "vis.scatter(\n",
    "    X=np.random.rand(6, 2),\n",
    "    opts=dict(\n",
    "        textlabels=['Label %d' % (i + 1) for i in range(6)]\n",
    "    )\n",
    ")"
   ],
   "id": "955ea1fd981c9d30",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'window_3e193de182e54c'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 9
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-22T13:29:57.131227Z",
     "start_time": "2025-05-22T13:29:56.991068Z"
    }
   },
   "cell_type": "code",
   "source": [
    "#三维散点图\n",
    "import visdom\n",
    "import numpy as np\n",
    "# 设置环境\n",
    "vis=visdom.Visdom(env='training_monitor')\n",
    "# 绘制3D散点图\n",
    "vis.scatter(\n",
    "    # X轴数据 随机生成100行3列数据\n",
    "    X=np.random.rand(100, 3),\n",
    "    # Y轴数据 随机生成100行1列数据\n",
    "    Y=(Y + 1.5).astype(int),\n",
    "    opts=dict(\n",
    "        legend=['男性', '女性'], # 图例标签\n",
    "        markersize=5, # 标记大小\n",
    "        xtickmin=0, # x轴刻度最小值\n",
    "        xtickmax=2, # x轴刻度最大值\n",
    "        xlabel='数量', # x轴标签\n",
    "        xtickvals=[0, 0.75, 1.6, 2], # x轴刻度值\n",
    "        ytickmin=0, # y轴刻度最小值\n",
    "        ytickmax=2, # y轴刻度最大值\n",
    "        ytickstep=0.5, # y轴刻度间隔\n",
    "        ztickmin=0, # z轴刻度最小值\n",
    "        ztickmax=1, # z轴刻度最大值\n",
    "        ztickstep=0.5, # z轴刻度间隔\n",
    "    )\n",
    ")"
   ],
   "id": "f88bb5f2a14b83d7",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Setting up a new session...\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'window_3e193ec6ddf61c'"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 11
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-22T13:41:03.048513Z",
     "start_time": "2025-05-22T13:41:02.715968Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import numpy as np\n",
    "import visdom\n",
    "\n",
    "vis=visdom.Visdom(env='training_monitor')\n",
    "\n",
    "# 基本线图\n",
    "vis.line(\n",
    "    Y=np.random.rand(10),\n",
    "    opts=dict(title='Basic Line', markers=True)\n",
    ")\n",
    "\n",
    "# 多线带图例\n",
    "vis.line(\n",
    "    X=np.arange(20),\n",
    "    Y=np.column_stack([np.sin(np.arange(20)), np.cos(np.arange(20))]),\n",
    "    opts=dict(\n",
    "        title='Trig Functions',\n",
    "        legend=['Sin', 'Cos'],\n",
    "        linecolor=np.array([[255,0,0], [0,0,255]]),  # 红蓝双线\n",
    "        dash=np.array(['solid', 'dash'])\n",
    "    )\n",
    ")"
   ],
   "id": "e09b2edb939790fa",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Setting up a new session...\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'window_3e194053c99b0c'"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 16
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-22T13:44:31.077141Z",
     "start_time": "2025-05-22T13:44:30.694801Z"
    }
   },
   "cell_type": "code",
   "source": [
    "#实线、虚线等不同线\n",
    "import visdom\n",
    "import numpy as np\n",
    "\n",
    "vis=visdom.Visdom(env='training_monitor')\n",
    "# 绘制三种线\n",
    "win = vis.line(\n",
    "    #  X轴数据 将三个在0和1之间的等差数列组成一个3列的矩阵\n",
    "    X=np.column_stack((\n",
    "        np.arange(0, 10),\n",
    "        np.arange(0, 10),\n",
    "        np.arange(0, 10),\n",
    "    )),\n",
    "    # Y轴数据 将三个在5和10之间的线性插值分别加上5、10后组成一个3列的矩阵\n",
    "    Y=np.column_stack((\n",
    "        np.linspace(5, 10, 10),\n",
    "        np.linspace(5, 10, 10) + 5,\n",
    "        np.linspace(5, 10, 10) + 10,\n",
    "    )),\n",
    "    opts={\n",
    "        'dash': np.array(['solid', 'dash', 'dashdot']),\n",
    "        'linecolor': np.array([\n",
    "            [0, 191, 255],\n",
    "            [0, 191, 255],\n",
    "            [255, 0, 0],\n",
    "        ]),\n",
    "        'title': '不同类型的线'\n",
    "    }\n",
    ")\n",
    "# 在之前创建的窗口win上继续绘制线条\n",
    "vis.line(\n",
    "    X=np.arange(0, 10), # X轴数据\n",
    "    Y=np.linspace(5, 10, 10) + 15, # Y轴数据\n",
    "    win=win, # 使用之前创建的窗口\n",
    "    name='4', # 线条名称\n",
    "    update='insert', # 更新方式为插入\n",
    "    opts={ # 绘制选项\n",
    "        'linecolor': np.array([ # 线条颜色\n",
    "            [255, 0, 0], # 红色\n",
    "        ]),\n",
    "        'dash': np.array(['dot']), # 线条样式 只包含点\n",
    "    }\n",
    ")"
   ],
   "id": "3557b60bd8854baa",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Setting up a new session...\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'window_3e1940cfc51f5a'"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 17
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-22T13:54:39.154534Z",
     "start_time": "2025-05-22T13:54:39.025094Z"
    }
   },
   "cell_type": "code",
   "source": [
    "#堆叠区域\n",
    "import visdom\n",
    "import numpy as np\n",
    "\n",
    "vis=visdom.Visdom(env='training_monitor')\n",
    "\n",
    "Y = np.linspace(0, 4, 200)\n",
    "win = vis.line(\n",
    "    Y=np.column_stack((np.sqrt(Y), np.sqrt(Y) + 2)),\n",
    "    X=np.column_stack((Y, Y)),\n",
    "    opts=dict(\n",
    "        fillarea=True, # 填充区域\n",
    "        showlegend=False, # 不显示图例\n",
    "        width=380, # 宽度\n",
    "        height=330, # 高度\n",
    "        ytype='log', # y轴类型\n",
    "        title='堆积面积图', # 标题\n",
    "        marginleft=30, # 左边距\n",
    "        marginright=30, # 右边距\n",
    "        marginbottom=80, # 底边距\n",
    "        margintop=30, # 上边距\n",
    "    ),\n",
    ")"
   ],
   "id": "a26ef49029b80d1d",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Setting up a new session...\n"
     ]
    }
   ],
   "execution_count": 20
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-22T14:10:08.664126Z",
     "start_time": "2025-05-22T14:10:08.533436Z"
    }
   },
   "cell_type": "code",
   "source": [
    "#茎叶图\n",
    "import math\n",
    "import visdom\n",
    "import numpy as np\n",
    "vis=visdom.Visdom(env='training_monitor')\n",
    "\n",
    "Y = np.linspace(0, 2 * math.pi, 70)\n",
    "X = np.column_stack((np.sin(Y), np.cos(Y)))\n",
    "vis.stem(\n",
    "    X=X,\n",
    "    Y=Y,\n",
    "    opts=dict(legend=['正弦函数', '余弦函数'])\n",
    ")"
   ],
   "id": "63e7a1a49296e5af",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Setting up a new session...\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'window_3e19446440ebd4'"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 24
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-22T14:13:30.121304Z",
     "start_time": "2025-05-22T14:13:29.982589Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import math\n",
    "import numpy as np\n",
    "import visdom\n",
    "\n",
    "vis = visdom.Visdom(env='training_monitor')\n",
    "\n",
    "# 生成X轴数据（自变量：角度）\n",
    "angles = np.linspace(0, 2 * math.pi, 70)  # 0到2π的70个点\n",
    "\n",
    "# 生成Y轴数据（因变量：函数值）\n",
    "function_values = np.column_stack((np.sin(angles), np.cos(angles)))  # 两列：sin和cos\n",
    "\n",
    "vis.stem(\n",
    "    X=function_values,  # 茎顶的位置（Y轴值）\n",
    "    Y=angles,           # 茎的位置（X轴值）\n",
    "    opts=dict(\n",
    "        legend=['sin(θ)', 'cos(θ)'],\n",
    "        title='茎叶图：sin和cos函数对比',\n",
    "        xtickvals=np.arange(0, 7, 1).tolist(),      # 使用 .tolist() 转换为 Python 列表\n",
    "        xticklabels=['0', '1', '2', '3', '4', '5', '6'],\n",
    "        ytickvals=np.arange(-1, 1.5, 0.5).tolist()   # 同样使用 .tolist()\n",
    "    )\n",
    ")\n"
   ],
   "id": "18e05302923689f1",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Setting up a new session...\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'window_3e1944dc54d64c'"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 29
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-22T14:34:00.175234Z",
     "start_time": "2025-05-22T14:18:03.969577Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "from torchvision import datasets, transforms\n",
    "from torch.utils.data import DataLoader\n",
    "import visdom\n",
    "\n",
    "# 初始化Visdom\n",
    "vis = visdom.Visdom(env='MNIST_Experiment')\n",
    "\n",
    "# 定义简单CNN模型\n",
    "class SimpleCNN(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(SimpleCNN, self).__init__()\n",
    "        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)\n",
    "        self.conv2 = nn.Conv2d(10, 20, kernel_size=5)\n",
    "        self.fc1 = nn.Linear(320, 50)\n",
    "        self.fc2 = nn.Linear(50, 10)\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = torch.relu(torch.max_pool2d(self.conv1(x), 2))\n",
    "        x = torch.relu(torch.max_pool2d(self.conv2(x), 2))\n",
    "        x = x.view(-1, 320)\n",
    "        x = torch.relu(self.fc1(x))\n",
    "        x = self.fc2(x)\n",
    "        return torch.log_softmax(x, dim=1)\n",
    "\n",
    "# 准备数据\n",
    "transform = transforms.Compose([transforms.ToTensor()])\n",
    "train_dataset = datasets.MNIST('./data', train=True, download=True, transform=transform)\n",
    "test_dataset = datasets.MNIST('./data', train=False, transform=transform)\n",
    "\n",
    "train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)\n",
    "test_loader = DataLoader(test_dataset, batch_size=1000, shuffle=False)\n",
    "\n",
    "# 初始化模型和优化器\n",
    "model = SimpleCNN()\n",
    "optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.5)\n",
    "criterion = nn.NLLLoss()\n",
    "\n",
    "# 训练函数\n",
    "def train(epoch):\n",
    "    model.train()\n",
    "    for batch_idx, (data, target) in enumerate(train_loader):\n",
    "        optimizer.zero_grad()\n",
    "        output = model(data)\n",
    "        loss = criterion(output, target)\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "\n",
    "        if batch_idx % 100 == 0:\n",
    "            vis.line(\n",
    "                X=[epoch * len(train_loader) + batch_idx],\n",
    "                Y=[loss.item()],\n",
    "                win='training_loss',\n",
    "                update='append' if epoch + batch_idx > 0 else None,\n",
    "                opts=dict(title='Training Loss', xlabel='Iterations', ylabel='Loss')\n",
    "            )\n",
    "\n",
    "# 测试函数\n",
    "def test(epoch):\n",
    "    model.eval()\n",
    "    test_loss = 0\n",
    "    correct = 0\n",
    "    with torch.no_grad():\n",
    "        for data, target in test_loader:\n",
    "            output = model(data)\n",
    "            test_loss += criterion(output, target).item()\n",
    "            pred = output.argmax(dim=1, keepdim=True)\n",
    "            correct += pred.eq(target.view_as(pred)).sum().item()\n",
    "\n",
    "    test_loss /= len(test_loader.dataset)\n",
    "    accuracy = 100. * correct / len(test_loader.dataset)\n",
    "\n",
    "    vis.line(\n",
    "        X=[epoch],\n",
    "        Y=[test_loss],\n",
    "        win='test_loss',\n",
    "        update='append' if epoch > 0 else None,\n",
    "        opts=dict(title='Test Loss', xlabel='Epoch', ylabel='Loss')\n",
    "    )\n",
    "\n",
    "    vis.line(\n",
    "        X=[epoch],\n",
    "        Y=[accuracy],\n",
    "        win='test_accuracy',\n",
    "        update='append' if epoch > 0 else None,\n",
    "        opts=dict(title='Test Accuracy', xlabel='Epoch', ylabel='Accuracy (%)')\n",
    "    )\n",
    "\n",
    "    # 可视化一些测试样本和预测结果\n",
    "    if epoch % 5 == 0:\n",
    "        sample_data = next(iter(test_loader))[0][:10]\n",
    "        outputs = model(sample_data)\n",
    "        preds = outputs.argmax(dim=1)\n",
    "\n",
    "        vis.images(\n",
    "            sample_data,\n",
    "            opts=dict(title=f'Predictions at Epoch {epoch}', caption=' '.join(str(p.item()) for p in preds))\n",
    "        )\n",
    "\n",
    "# 运行训练和测试\n",
    "for epoch in range(1, 11):\n",
    "    train(epoch)\n",
    "    test(epoch)"
   ],
   "id": "d1e41f37ea89ca04",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Setting up a new session...\n",
      "100.0%\n",
      "100.0%\n",
      "100.0%\n",
      "100.0%\n"
     ]
    }
   ],
   "execution_count": 30
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-23T00:23:33.548750Z",
     "start_time": "2025-05-23T00:23:27.276024Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "writer = SummaryWriter(log_dir = 'test')"
   ],
   "id": "54001af3c201e56c",
   "outputs": [],
   "execution_count": 1
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-23T00:24:18.574619Z",
     "start_time": "2025-05-23T00:24:18.549979Z"
    }
   },
   "cell_type": "code",
   "source": "writer.log_dir",
   "id": "96d737603a046f68",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'test'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 2
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-05-23T00:24:28.723814Z",
     "start_time": "2025-05-23T00:24:28.705686Z"
    }
   },
   "cell_type": "code",
   "source": [
    "for i in range(10):\n",
    "    writer.add_scalar('mul', i*i, i)"
   ],
   "id": "607c60c4317e4e3f",
   "outputs": [],
   "execution_count": 3
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pytorch_stu",
   "language": "python",
   "name": "pytorch_stu"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
